package com.xx.util;

import cn.hutool.core.util.StrUtil;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description: ais命令工具
 * @author: xx
 * @Date 2023/7/19 15:04
 * @version: 1.0
 */
public class AisCommandUtil {
    private static AtomicInteger atomicInteger = new AtomicInteger();

    public static List<String> xToY_send(int mmsi, String type, String command, String text) {
        byte[] sendData = text.getBytes(Charset.forName("GB2312"));
        int y1, y2;
        StringBuilder sb = new StringBuilder();
        //sb.append("0110011101000001");
        sb.append(send_8bit(0x67)).append(send_8bit(0x41));
        for (int i = 0; i < sendData.length; i++) {
            //x1取机内码
            int x1 = (sendData[i] & 0xFF);
            if (x1 < 0x80) {
                if (x1 >= 0x40) { //x1最高位为0,x1转换为7位手法代码(ASCII码)y1
                    y1 = x1 - 0x40;
                } else {
                    y1 = x1;
                }
                sb.append(send_7bit(y1)); //把7位收发代码y1送入发送数据区
            } else { // x1最高位为1,x1,x2转换为手法代码(汉字码) y1,y2
                //x2取机内码
                int x2 = (sendData[++i] & 0xFF);
                int AA = x1 & 0x7f; //x1,x2最高位请0,成14位孩子码 AA,BB
                int BB = x2 & 0x7f;
                //将14位汉字码转AA,BB 转换为汉字13位码 a,b
                int b, a;
                if (AA < 0x40) {
                    b = BB / 0x20;
                    a = (AA - 0x30) * 4 + b;
                    b = BB % 0x20;
                } else {
                    a = AA - 0x40;
                    b = BB;
                }
                y1 = a | 0x40; //汉字码填上最高位1,成14位收发代码y1,y2
                y2 = b;
                sb.append(send_7bit(y1)); //把y1,y2两个7位收发代码送入发送数据区
                sb.append(send_7bit(y2));
            }
        }
        String binaryStr = sb.toString();
        StringBuilder stb = new StringBuilder();
        int padding = 0;
        for (int i = 0; i < binaryStr.length(); i += 6) {
            String group = binaryStr.substring(i, Math.min(i + 6, binaryStr.length()));
            while (group.length() < 6) {
                group += "0";
                padding++;
            }
            //IF Y＜28H THEN X＝Y＋30H
            //ELSE X＝Y＋38H。
            int asciiCode = Integer.parseInt(group, 2);
            if (asciiCode < 0x28) {
                asciiCode = asciiCode + 0x30;
            } else {
                asciiCode = asciiCode + 0x38;
            }
            stb.append((char) asciiCode);
        }
        String format;
        ArrayList<String> list = new ArrayList<>();
        if ("ABM".equals(type)) {
            String cm = "$--ABM,{},{},{},{},3,6,{},{}*";

            if (stb.length() > 48) {
                String substring = stb.substring(0, 48);
                list.add(substring);
                String subEnd = stb.substring(48, stb.length());
                for (int i = 0; i < subEnd.length(); i += 60) {
                    String sub = subEnd.substring(i, Math.min(i + 60, subEnd.length()));
                    list.add(sub);
                }
            }
            int atint = getAtomicInteger();
            for (int i = 0; i < list.size(); i++) {
                format = StrUtil.format(cm, i + 1,list.size(),atint, mmsi, list.get(i), padding);
                ;
                list.set(i, checkCode(format));
            }
        } else {
            format = StrUtil.format("$--ABM,1,1,{},{},3,6,{},{}*", getAtomicInteger(), mmsi, stb, padding);
            list.add(checkCode(format));
        }
//        String s = "$--ABM,1,1,2,{},3,6," + stb + "," + padding + "*";

        return list;
    }


    public static String checkCode(String aisMessage) {
        // 计算校验和
        int checksum = 0;
        for (char c : aisMessage.toCharArray()) {
            if (c == '!' || c == '$') { // 跳过消息标识符
                continue;
            }
            if (c == '*') { // 校验和字段之后的字符不再计入校验和
                break;
            }
            checksum ^= c;
        }
        // 将校验和转换为两位十六进制数
        String checksumHex = String.format("%02X", checksum);
        return aisMessage + checksumHex + "\r\n";
    }

    private static String send_7bit(int y1) {
        String binaryString = Integer.toBinaryString(y1);
        while (binaryString.length() < 7) {
            binaryString = "0" + binaryString;
        }
        return binaryString.substring(binaryString.length() - 7);
    }

    private static String send_8bit(int y1) {
        String binaryString = Integer.toBinaryString(y1);
        while (binaryString.length() < 8) {
            binaryString = "0" + binaryString;
        }
        return binaryString.substring(binaryString.length() - 8);
    }

    private static int getAtomicInteger() {
        int i = atomicInteger.incrementAndGet();
        if (i > 3) {
            atomicInteger.set(1);
            return atomicInteger.get();
        }
        return i;
    }
}
